gusucode.com > VC++视频目标检测演示帧间差分法-源码程序 > VC++视频目标检测演示帧间差分法-源码程序/code/Video Demo/MeanShiftSegger.cpp

    //Download by http://www.NewXing.com
#include "MeanShiftSegger.h"
#include "math.h"


int max(int x,int y)
{
	if(x > y)
		return x;

	return y;

}
int min(int x,int y)
{
	if(x > y)
		return y;

	return x;

}
/***********************************************************************
* 函数名称:
*     MeanShiftSegger()
*
*说明:构造函数 
***********************************************************************/
MeanShiftSegger::MeanShiftSegger():
imgWidth(0),imgHeight(0){
    for(int i = 0; i < HISTOGRAM_LENGTH; i ++)
		currHistogram[i] = 0;
    for(i = 0; i < HISTOGRAM_LENGTH; i ++)
		tempHistogram[i] = 0;
	//memset(currHistogram,0,sizeof(float) * HISTOGRAM_LENGTH);
	//memset(tempHistogram,0,sizeof(float) * HISTOGRAM_LENGTH);
	//SetZeroHistogram(currHistogram);
	//SetZeroHistogram(tempHistogram);
	return;

}
/***********************************************************************
* 函数名称:
*     ~MeanShiftSegger()
* 说明:
*     析构函数
***********************************************************************/
MeanShiftSegger::~MeanShiftSegger(){

}

/***********************************************************************
* 函数名称:
*     InitMeanShiftTracker()
* 参数:
*     unsigned char * firstFrame 第一帧缓冲
*     int frameWidth-帧宽度
*     int frameHeight-帧高度
*     int targetPosX-目标位置横坐标
*     int targetPosY-目标位置纵坐标
*     int targetWidth-目标宽度
*     int targetHeight-目标高度
* 说明:MeanShift过程跟踪初始化程序
***********************************************************************/

void MeanShiftSegger::InitMeanShiftTracker(unsigned char*  firstFrame,int frameWidth,int frameHeight,int targetPosX,int targetPosY,int targetWidth,int targetHeight){
	this->imgWidth = frameWidth;
	this->imgHeight = frameHeight;

	this->currentX = targetPosX;
	this->currentY = targetPosY;

	this->trackWinHeight = targetHeight;
	this->trackWinWidth = targetWidth;
}


/***********************************************************************
* 函数名称:
*     CalculateHistogramSp
* 参数:
*     image frame-当前输入帧
*     char kernel-核类型选择(目前只支持Uniform核)
*     float * histogram-直方图缓冲
* 说明:统计直方图,建立区域模型(无参数概率密度估计)
***********************************************************************/
int MeanShiftSegger::CalculateHistogramSp(unsigned char*  frame,char kernel, float *histogram){
	int pxValue = 0;

	for(int i = 0 ; i < HISTOGRAM_LENGTH; i++)
		histogram[i] = 0;

	if(kernel == 'U')
	{

		for(int j = max(0,currentY - trackWinHeight / 2);j < min(currentY + trackWinHeight / 2,imgHeight - 1); j ++){
			for(int i = max(0,currentX - trackWinWidth / 2); i < min(currentX + trackWinWidth / 2,imgWidth - 1);i ++){
				pixel r = frame[j * imgWidth * 3 + i * 3] / 16;
				pixel g = frame[j * imgWidth * 3 + i * 3 + 1] / 16;
				pixel b = frame[j * imgWidth * 3 + i * 3 + 2] / 16;

				histogram[256 * (int)r + 16 * (int)g + (int)b] += 1;
				pxValue ++;

			}

		}

		for(int i = 0; i < HISTOGRAM_LENGTH; i ++)
			histogram[i] /= pxValue;
	}
	else
	{
		return 0;
	}
	return pxValue;
}

/***********************************************************************
* 函数名称:
*     MeanShiftTrackerProcess
* 参数:
*     unsigned char *frame-当前帧缓冲
* 说明:跟踪中的MeanShift过程
***********************************************************************/
void MeanShiftSegger::MeanShiftProcessSp(unsigned char * frame){
	float weights[HISTOGRAM_LENGTH];

	float newX = 0.0;
	float newY = 0.0;

	for (int i=0;i<HISTOGRAM_LENGTH;i++)
	{
		if (currHistogram[i] >0.0 )
			weights[i] = (float)tempHistogram[i]/(float)currHistogram[i];
		//目标模板直方图/当前直方图
		else
			weights[i] = 0;
	}

	float sumOfWeights = 0.0;

		for(int j = max(0,currentY - trackWinHeight / 2);j < min(currentY + trackWinHeight / 2,imgHeight - 1); j ++){
			for(int i = max(0,currentX - trackWinWidth / 2); i < min(currentX + trackWinWidth / 2,imgWidth - 1);i ++){
			pixel r = frame[j * imgWidth * 3 + i * 3] / 16;
			pixel g = frame[j * imgWidth * 3 + i * 3 + 1] / 16;
			pixel b = frame[j * imgWidth * 3 + i * 3 + 2] / 16;

			int ptr = (int)(256 * (int)r + 16 * (int)g + (int)b);

			newX += (weights[ptr] * (float)i);
			newY += (weights[ptr] * (float)j);

			sumOfWeights += weights[ptr];


		}

	}
	if(sumOfWeights != 0){
		currentX = int((newX/sumOfWeights) + 0.5);
		currentY = int((newY/sumOfWeights) + 0.5);
	}
	return;

}


/***********************************************************************
* 函数名称
*     MeanShiftTrackProcess 
* 参数:
*     image frame-当前输入帧
*     int frameNumber-输入帧号
* 说明:MeanShift跟踪主调用过程
***********************************************************************/
void MeanShiftSegger::MeanShiftTrackProcess(unsigned char*  frame,int frameNumber)
{
	if(frameNumber == 0){
		//在指定位置建立目标模型
		CalculateHistogramSp(frame,'U',this->tempHistogram);
	}
	else
	{
		int stopThreshold = 10;
		int iteratorCoumt = 0;
		while(iteratorCoumt < stopThreshold){

			//在后续帧中检测目标新位置
			CalculateHistogramSp(frame,'U',this->currHistogram);
			MeanShiftProcessSp(frame); //获得新位置

			//更新直方图
			iteratorCoumt++;
		}
		
		DrawTrackBox(frame);

	}
}


/***********************************************************************
* 函数名称:
*     DrawTrackBox
* 参数:
*     unsigned char * frame-当前帧缓冲
* 说明:在输出中画跟踪窗口
***********************************************************************/
void MeanShiftSegger::DrawTrackBox(unsigned char*  frame)
{

	for(int i = currentX; i < min(imgWidth,currentX + trackWinWidth); i ++)
	{
		frame[currentY * imgWidth * 3 + i * 3 + 0] = 0;
		frame[currentY * imgWidth * 3 + i * 3 + 1] = 0;
		frame[currentY * imgWidth * 3 + i * 3 + 2] = 255;

		frame[min(imgHeight - 1,currentY + trackWinHeight) * imgWidth * 3 + i * 3 + 0] = 0;
		frame[min(imgHeight - 1,currentY + trackWinHeight) * imgWidth * 3 + i * 3 + 1] = 0;
		frame[min(imgHeight - 1,currentY + trackWinHeight) * imgWidth * 3 + i * 3 + 2] = 255;
	}

	for(int j = currentY; j < min(imgHeight - 1,currentY + trackWinHeight); j ++)
	{

		frame[j * imgWidth * 3 + currentX * 3 + 0] = 0;
		frame[j * imgWidth * 3 + currentX * 3 + 1] = 0;
		frame[j * imgWidth * 3 + currentX * 3 + 2] = 255;

		frame[j * imgWidth * 3 + min(imgWidth - 1,currentX + trackWinWidth) * 3 + 0] = 0;
		frame[j * imgWidth * 3 + min(imgWidth - 1,currentX + trackWinWidth) * 3 + 1] = 0;
		frame[j * imgWidth * 3 + min(imgWidth - 1,currentX + trackWinWidth) * 3 + 2] = 255;
	}


}

/***********************************************************************
* 函数名称:
*     CalculateBhattacharyya
* 说明:计算Bhattachryya
***********************************************************************/
float MeanShiftSegger::CalculateBhattacharyya(float initHistogram [HISTOGRAM_LENGTH],float tempHistogram[HISTOGRAM_LENGTH]){
	float dis = 0;

	for(int i = 0;i < HISTOGRAM_LENGTH ;i ++)
		dis += float(sqrt(double(currHistogram[i] * tempHistogram[i])));

	return dis;
}